package ldh.fx.adminfx;

import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXDecorator;
import com.jfoenix.controls.JFXPopup;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import ldh.fx.adminfx.controller.LoginController;
import ldh.fx.adminfx.fxanimations.FadeInTransition;
import ldh.fx.adminfx.fxanimations.FadeOutUpBigTransition;
import ldh.fx.adminfx.pojo.FxmlBean;
import ldh.fx.adminfx.util.LoggerUtil;
import ldh.fx.adminfx.util.RegionUtil;
import ldh.fx.adminfx.util.StageUtil;
import ldh.fx.adminfx.util.ThreadPoolUtil;

import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;

public abstract class AbstractFxGui extends Application {

    private final static Logger LOGGER = LoggerUtil.getFileLogger(AbstractFxGui.class);

    private static Map<String, Set<String>> cssMap = new LinkedHashMap<>();
    public static String currentCss = "蓝色";
    private JFXPopup cssPop = null;

    @Override
    public void start(Stage primaryStage) throws Exception {
        LOGGER.info("start!!!!");
        StageUtil.setStage(primaryStage);
        try {
            Pane pane = buildApp(primaryStage);
            pane.setOpacity(0);
            primaryStage.show();

            showLogin(primaryStage, pane);
        } catch (Exception e) {
            LOGGER.log(Level.SEVERE, e.getMessage(), e);
            throw e;
        }
    }

    public Pane buildApp(Stage primaryStage) {
        initCss();

        Image icon = new Image(this.getClass().getResource("/img/logo.png").toExternalForm());
        JFXDecorator jfxDecorator = buildJFXDecorator(primaryStage);

        primaryStage.initStyle(StageStyle.TRANSPARENT);

        StackPane stackPane = new StackPane();
        stackPane.getStyleClass().add("root-pane");
        Pane shadowPane = new Pane();
//        shadowPane.widthProperty().bind(stackPane.widthProperty());
//        shadowPane.heightProperty().bind(stackPane.heightProperty());
        shadowPane.getStyleClass().add("shadow-pane");
        stackPane.getChildren().addAll(shadowPane, jfxDecorator);

        jfxDecorator.setOnCloseButtonAction(()->{
            FadeOutUpBigTransition fadeOutUpBigTransition = new FadeOutUpBigTransition(stackPane);
            fadeOutUpBigTransition.setOnFinished(e->{
                primaryStage.close();
                ThreadPoolUtil.close();
            });
            fadeOutUpBigTransition.playFromStart();
        });

        Scene scene = new Scene(stackPane, 1100, 700);
        scene.setFill(null);

        setCss(scene, currentCss);
        loadOtherCss(scene);

        buildHead(scene, jfxDecorator, icon);

        primaryStage.fullScreenProperty().addListener((ob, n, o)->{
            Node node = jfxDecorator.lookup(".jfx-decorator-content-container");
            if (ob.getValue() || primaryStage.isMaximized()) {
                node.getStyleClass().remove("jfx-decorator-border");
                node.getStyleClass().add("jfx-decorator-width-clear");
                shadowPane.getStyleClass().remove("shadow-pane");
                stackPane.getStyleClass().remove("root-pane");
            } else {
                node.getStyleClass().remove("jfx-decorator-width-clear");
                node.getStyleClass().add("jfx-decorator-border");
                shadowPane.getStyleClass().add("shadow-pane");
                stackPane.getStyleClass().add("root-pane");
            }
        });

        primaryStage.maximizedProperty().addListener((ob, n, o)->{
            if (ob.getValue()) {
                shadowPane.getStyleClass().remove("shadow-pane");
                stackPane.getStyleClass().remove("root-pane");
            } else {
                shadowPane.getStyleClass().add("shadow-pane");
                stackPane.getStyleClass().add("root-pane");
            }
        });

        scene.getStylesheets().add(this.getClass().getResource("/css/init.css").toExternalForm());
        scene.getStylesheets().add(this.getClass().getResource("/css/skin/base.css").toExternalForm());
        scene.getStylesheets().add(this.getClass().getResource("/css/ui.css").toExternalForm());
//        scene.getStylesheets().add("org/kordamp/bootstrapfx/bootstrapfx.css");
        scene.getStylesheets().add(this.getClass().getResource("/css/bootstrapfx.css").toExternalForm());
        scene.getStylesheets().add(this.getClass().getResource("/css/chart.css").toExternalForm());
        scene.getStylesheets().add(this.getClass().getResource("/css/component/scrollpane.css").toExternalForm());
        scene.getStylesheets().add(this.getClass().getResource("/css/component/list.css").toExternalForm());

        primaryStage.getIcons().add(icon);
        primaryStage.setScene(scene);
        primaryStage.setTitle("Javafx GUI 后台");

        return stackPane;
    }

    private void showLogin(Stage primaryStage, Node node) {
        Stage stage = new Stage();
        stage.initOwner(primaryStage);

        FxmlBean<AnchorPane, LoginController> loginBean = RegionUtil.loadFxmlBean("/fxml/LoginPage.fxml");
        loginBean.getController().setConsumer((Void)->{
            primaryStage.show();
            FadeInTransition fadeInTransition = new FadeInTransition(node);
            fadeInTransition.playFromStart();
        });
        Scene scene = loginBean.getController().createScene();
        stage.setScene(scene);
        scene.setFill(null);
        stage.initStyle(StageStyle.TRANSPARENT);
        stage.centerOnScreen();

//        loginBean.getController().getRoot().setOpacity(0);
        stage.show();
        stage.toFront();

//        FadeInTransition fadeInRightTransition = new FadeInTransition(loginBean.getController().getRoot());
//        fadeInRightTransition.setDelay(new Duration(800));
//        fadeInRightTransition.playFromStart();
    }


    private void buildHead(Scene scene, JFXDecorator jfxDecorator, Image icon) {
        HBox head = (HBox) jfxDecorator.lookup(".jfx-decorator-title-container");
        ImageView imageView = new ImageView(icon);
        imageView.setFitHeight(30);
        imageView.setFitWidth(40);
        head.getChildren().add(0, imageView);

        HBox headButs = (HBox) jfxDecorator.lookup(".jfx-decorator-buttons-container");
        JFXButton cssBtn = new JFXButton("皮肤");
        VBox cssPopNode = buildCssNode(scene, cssBtn);
        cssPop = new JFXPopup(cssPopNode);
        cssBtn.setOnAction(e->{
            cssPop.show(cssBtn, JFXPopup.PopupVPosition.TOP, JFXPopup.PopupHPosition.RIGHT);
        });
        headButs.getChildren().add(2, cssBtn);
    }

    private JFXDecorator buildJFXDecorator(Stage primaryStage) {
        Pane mainPane = createMainPane();
        JFXDecorator jfxDecorator = new JFXDecorator(primaryStage, mainPane);
        Node node = jfxDecorator.lookup(".jfx-decorator-content-container");
        node.getStyleClass().add("jfx-decorator-border");
        return jfxDecorator;
    }

    protected abstract Pane createMainPane();

    private VBox buildCssNode(Scene scene, JFXButton cssBtn) {
        VBox menu = new VBox();
        menu.getStyleClass().add("popup-content");
        menu.setSpacing(10);
        menu.setPadding(new Insets(10, 10, 10, 10));
        cssMap.forEach((k, v)->{
            JFXButton jfxButton = new JFXButton(k.toLowerCase());
            jfxButton.getStyleClass().add("css-item");
            menu.getChildren().add(jfxButton);
            jfxButton.setOnAction(e->{
                currentCss = k;
                cssBtn.setText(k);
                setCss(scene, currentCss);
                cssPop.hide();
            });
        });
        return menu;
    }

    private void setCss(Scene scene, String cssKey) {
        Set<String> removes = cssMap.get(currentCss);
        if (removes != null) {
            scene.getStylesheets().removeAll(removes);
        }
        currentCss = cssKey;
        scene.getStylesheets().addAll(cssMap.get(cssKey));
    }

    protected void initCss() {
        addCss("黑色", AbstractFxGui.class.getResource("/css/skin/dark.css").toExternalForm());
        addCss("蓝色", AbstractFxGui.class.getResource("/css/skin/blue.css").toExternalForm());
        addCss("绿色", AbstractFxGui.class.getResource("/css/skin/green.css").toExternalForm());
        addCss("赤金", AbstractFxGui.class.getResource("/css/skin/gold.css").toExternalForm());
        addCss("橙色", AbstractFxGui.class.getResource("/css/skin/salmon.css").toExternalForm());
        addCss("灰色", AbstractFxGui.class.getResource("/css/skin/gray.css").toExternalForm());
        addCss("象牙白", AbstractFxGui.class.getResource("/css/skin/white.css").toExternalForm());
    }

    protected void addCss(String key, String cssFile) {
        Set<String> cssFiles = cssMap.get(key);
        if (cssFiles == null) cssFiles = new LinkedHashSet<>();
        cssFiles.add(cssFile);
        cssMap.put(key, cssFiles);
    }

    protected void loadOtherCss(Scene scene){}
}
